<?php defined('SYSPATH') or die('No direct script access.');

class WizardController extends Controller {

    public $data;
    protected $stepUrl;
    private $wizardDataClass;
    private $wizardPath;
    private $steps;

    public function __construct($wizardDataClass, $wizardPath, $contentLayout, $steps) {
        parent::__construct();
        $this->wizardDataClass = $wizardDataClass;
        $this->wizardPath = $wizardPath;
        $this->contentLayout = $contentLayout;
        $this->steps = $steps;

        /*
         * Note: $this->steps should be dropped when PHP 5.3 is available, since
         * we can get it as $wizardDataClass::$STEPS
         */

        $this->stepUrl = $this->wizardPath . '/step';

        $getDataMethod = 'get' . $this->wizardDataClass;
        $this->data = $this->getSessionData()->$getDataMethod();
        if (! $this->data) {
            if (Router::$method != 'enter') {
                $this->restart();
            }
        }
    }

    protected function redirectToStep() {
        $this->redirect($this->stepUrl);
    }

    public function index() {
        $this->step();
    }

    protected function newData() {
        $this->data = new $this->wizardDataClass();
        $setDataMethod = 'set' . $this->wizardDataClass;
        $this->getSessionData()->$setDataMethod($this->data);
    }
    
    public function restart() {
        $this->newData();

        // Go to the first step of the wizard.
        $this->redirectToStep();
    }

    public function next() {
        // TODO Must be called by POST
        $nextStep = false;
        foreach ($this->steps as $step) {
            if ($nextStep) {
                // Call the corresponding method
                $functionName = $this->data->step . 'Next';
                $returnValue = $this->$functionName();

                // If the return value is FALSE, then the method did not accept
                // the data and we must return to the current step form.
                if ($returnValue === FALSE) {
                    $functionName = $this->data->step . 'Data';
                    if (method_exists($this, $functionName)) {
                        $this->$functionName();
                    }
                    $this->renderSubview($this->wizardPath . '/' . $this->data->step . 'Step');
                    return;
                }
                // Move to the next step
                $this->data->step = $step;
                $this->redirectToStep();
            }
            if ($this->data->step == $step) {
                // Redirect to the next step.
                $nextStep = true;
            }
        }
        // FIXME log this problem
        $this->redirect($this->wizardPath . '/restart');
    }

    public function step() {
        // TODO Must be called by GET
        if ($this->data->step) {
            $functionName = $this->data->step . 'Step';
            if (method_exists($this, $functionName)) {
                $this->$functionName();
                $this->renderSubview($this->wizardPath . '/' . $this->data->step . 'Step');
            }
            else {
                die('Invalid method: ' . $functionName);
            }
        }
        else {
            die('Invalid state: unknown wizard step.');
        }
    }

    public function jump() {
        $jumpToStep = $this->input->get('to');
        foreach ($this->steps as $step) {
            if ($jumpToStep == $step) {
                $this->data->goBackToStep($step);
                $this->redirectToStep();
            }
            if ($this->data->step == $step) {
                break;
            }
        }
        $this->redirectToStep();
    }

    public function previous() {
        $previousStep = null;
        foreach ($this->steps as $step) {
            if ($this->data->step == $step) {
                if ($previousStep != NULL) {
                    // if ($previousStep == $this->steps[0]) {
                    //     $this->restart();
                    // }
                    // else {
                        $this->data->goBackToStep($previousStep);
                        $this->redirectToStep();
                    // }
                }
                else {
                    $this->restart();
                }
                return;
            }
            $previousStep = $step;
        }
    }

    protected function clearData() {
        $setDataMethod = 'set' . $this->wizardDataClass;
        $this->getSessionData()->$setDataMethod(NULL);
    }
}